package core

import (
	"dgo/MyProj/PrjConf"
	"dgo/MyProj/PrjHttpClt"
	"dgo/goutils/utils"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"os"
	"strings"
	"time"
)

type loggerNet struct {
	log_url  string
	postType string
	conf     *wrapper.SuperValue
	loggerW  *utils.LoggerCacheWriter
}

func (this *loggerNet) innerPostTypeTxt(cacheQueue *utils.QueueTask) {
	var sb utils.BytesBuilder
	cacheQueue.PopTaskArgMaxFunc(10, func(args ...interface{}) bool {
		rec := args[0].(*utils.LogRecord)
		sb.Appendf("%X,%s,%s,%s,%s\r\n", rec.Created.Unix(), rec.Typestr, utils.LogLvlStr(rec.Level), rec.Source, utils.EscapeJsonStrSimple(rec.Msg))
		return true
	})
	logurl := strings.ReplaceAll(this.log_url, "$appuuid$", PrjConf.APP_UUID)

	if sb.Len() > 0 {
		i := 0
		var lasterr error
		for i < 10 { // 最多重试10次
			_, lasterr = PrjHttpClt.PostRawBuf(logurl, sb.Bytes(), "application/text")
			if lasterr == nil {
				break
			}
			// 提交出错, 休息
			time.Sleep(time.Second * time.Duration(i))
			i++
		}

		if lasterr != nil {
			fmt.Fprintf(os.Stderr, "提交网络(%s)日志(%s)异常:%s", logurl, utils.HumanFilesize(int64(sb.Len())), lasterr)
		}
	}
}

func (this *loggerNet) innerPostTypeJson(cacheQueue *utils.QueueTask) {
	json := wrapper.NewSVObject()
	lst := json.ForceArrayByPath("list")
	n := cacheQueue.PopTaskArgMaxFunc(10, func(args ...interface{}) bool {
		rec := args[0].(*utils.LogRecord)
		itm := lst.AppendObject()
		itm.SetKeyValues("t", rec.Created.Unix(), "type", rec.Typestr, "lvl", utils.LogLvlStr(rec.Level), "src", rec.Source, "msg", rec.Msg)
		return true
	})
	if n > 0 {
		logurl := strings.ReplaceAll(this.log_url, "$appuuid$", PrjConf.APP_UUID)
		i := 0
		logBuf := json.AsJSONBytes(false)
		var lasterr error
		for i < 10 { // 最多重试10次
			_, lasterr = PrjHttpClt.PostRawBuf(logurl, logBuf, "application/json")
			if lasterr == nil {
				break
			}
			// 提交出错, 休息
			time.Sleep(time.Second * time.Duration(i))
			i++
		}

		if lasterr != nil {
			fmt.Fprintf(os.Stderr, "提交网络(%s)日志(%s)异常:%s", logurl, utils.HumanFilesize(int64(len(logBuf))), lasterr)
		}
	}
}

/*
*
// fmt.Sprintf("%s/sys/log/add?id=%s&type=%s", "http://121.36.207.51:9004", PrjConf.APP_UUID, "NETLOCKER")

	{
	   "url":"http://121.36.207.51:9004/sys/log/add?id=$appuuid$&type=GNSS",
	   "loglvl":"DEBUG",
	   "post_type":"txt", // 默认 json
	   "loglvlop":">="
	}
*/
func (this *loggerNet) ReloadConf(conf *wrapper.SuperValue) error {

	conf.CheckExistsStrFunc("post_type", func(strv string) {
		this.postType = strv
	})
	if sflogger, ok := utils.Log.(*utils.SafeLogger); ok {
		this.log_url = conf.StringByName("url", "")
		if strings.Index(this.log_url, "$appuuid$") != -1 {
			if len(PrjConf.APP_UUID) == 0 {
				PrjConf.MakeAppUUIDByStartupArgs("")
			}
		}
		log_lvl := utils.LogLvlStr2Lvl(conf.StringByName("loglvl", ""))
		opstr := conf.StringByName("loglvlOp", ">=")
		log_op := utils.LogOperaStr2LogOp(opstr)
		if this.loggerW != nil {
			this.loggerW.SetLvlFilter(log_lvl, log_op)
			utils.Log.InfoTypef("STATE", "修改日志配置(%s %s) url:%s", opstr, utils.LogLvlStr(log_lvl), this.log_url)
			return nil
		}
		clw := utils.NewLoggerCacheWriter(1024, time.Second*10, func(cacheQueue *utils.QueueTask) {
			if this.postType == "json" {
				this.innerPostTypeJson(cacheQueue)
			} else {
				this.innerPostTypeTxt(cacheQueue)
			}
		})
		clw.SetLvlFilter(log_lvl, log_op)
		this.loggerW = clw
		sflogger.AddWriter(clw)
		return nil
	} else {
		return fmt.Errorf("log 非SafeLogger不能进行该日志的创建")
	}
}

func (this *loggerNet) OnObjectNotify(sender interface{}, notifytype int, data interface{}) (rval interface{}, err error) {
	if notifytype == utils.NOTIFY_TYPE_SETCONF {
		if conf, ok := data.(*wrapper.SuperValue); ok {
			err = this.ReloadConf(conf)
		}
	} else if notifytype == utils.NOTIFY_TYPE_RELEASE {
		if this.loggerW != nil {
			if sflogger, ok := utils.Log.(*utils.SafeLogger); ok {
				sflogger.RemoveWriter(this.loggerW)
			}
			this.loggerW.Close()
			this.loggerW = nil
		}
	}
	return
}

func CreateLoggerNetPlugFunc(args ...interface{}) (rval interface{}, err error) {
	return &loggerNet{}, nil
}
